209 lines
6.8 KiB
Clojure
209 lines
6.8 KiB
Clojure
(ns status-im.ui.components.react
|
|
(:require-macros [status-im.utils.views :as views])
|
|
(:require [clojure.string :as string]
|
|
[reagent.core :as r]
|
|
[status-im.ui.components.styles :as st]
|
|
[status-im.utils.utils :as u]
|
|
[status-im.utils.platform :refer [platform-specific ios?]]
|
|
[status-im.i18n :as i18n]
|
|
[status-im.react-native.js-dependencies :as rn-dependencies]))
|
|
|
|
(defn get-react-property [name]
|
|
(if rn-dependencies/react-native
|
|
(aget rn-dependencies/react-native name)
|
|
#js {}))
|
|
|
|
(defn adapt-class [class]
|
|
(when class
|
|
(r/adapt-react-class class)))
|
|
|
|
(defn get-class [name]
|
|
(adapt-class (get-react-property name)))
|
|
|
|
(def native-modules (.-NativeModules rn-dependencies/react-native))
|
|
(def device-event-emitter (.-DeviceEventEmitter rn-dependencies/react-native))
|
|
(def dismiss-keyboard! rn-dependencies/dismiss-keyboard)
|
|
(def orientation rn-dependencies/orientation)
|
|
(def back-handler (get-react-property "BackHandler"))
|
|
(def drawer rn-dependencies/drawer)
|
|
|
|
(def splash-screen (.-SplashScreen native-modules))
|
|
|
|
;; React Components
|
|
|
|
(def app-registry (get-react-property "AppRegistry"))
|
|
(def app-state (get-react-property "AppState"))
|
|
(def net-info (get-react-property "NetInfo"))
|
|
(def geolocation (when (exists? js/window)
|
|
js/navigator.geolocation.))
|
|
(def view (get-class "View"))
|
|
|
|
(def status-bar (get-class "StatusBar"))
|
|
(def drawer-layout (adapt-class (.-default drawer)))
|
|
|
|
(def scroll-view (get-class "ScrollView"))
|
|
(def web-view (get-class "WebView"))
|
|
(def keyboard-avoiding-view-class (get-class "KeyboardAvoidingView"))
|
|
|
|
(def text-class (get-class "Text"))
|
|
(def text-input-class (get-class "TextInput"))
|
|
(def image (get-class "Image"))
|
|
|
|
(def touchable-without-feedback (get-class "TouchableWithoutFeedback"))
|
|
(def touchable-highlight-class (get-class "TouchableHighlight"))
|
|
(def touchable-opacity (get-class "TouchableOpacity"))
|
|
(def activity-indicator (get-class "ActivityIndicator"))
|
|
|
|
(def modal (get-class "Modal"))
|
|
(def picker-class (get-class "Picker"))
|
|
(def picker-item-class
|
|
(when-let [picker (get-react-property "Picker")]
|
|
(adapt-class (.-Item picker))))
|
|
|
|
(def pan-responder (.-PanResponder rn-dependencies/react-native))
|
|
(def animated (.-Animated rn-dependencies/react-native))
|
|
(def animated-view (r/adapt-react-class (.-View animated)))
|
|
(def animated-text (r/adapt-react-class (.-Text animated)))
|
|
|
|
(def dimensions (.-Dimensions rn-dependencies/react-native))
|
|
(def keyboard (.-Keyboard rn-dependencies/react-native))
|
|
(def linking (.-Linking rn-dependencies/react-native))
|
|
|
|
(def slider (get-class "Slider"))
|
|
;; Accessor methods for React Components
|
|
|
|
(defn add-font-style [style-key {:keys [font] :as opts :or {font :default}}]
|
|
(let [font (get-in platform-specific [:fonts (keyword font)])
|
|
style (get opts style-key)]
|
|
(-> opts
|
|
(dissoc :font)
|
|
(assoc style-key (merge style font)))))
|
|
|
|
(defn text
|
|
([t]
|
|
(r/as-element [text-class t]))
|
|
([{:keys [uppercase?] :as opts} t & ts]
|
|
(r/as-element
|
|
(let [ts (cond->> (conj ts t)
|
|
uppercase? (map #(when % (string/upper-case %))))]
|
|
(vec (concat
|
|
[text-class (add-font-style :style opts)]
|
|
ts))))))
|
|
|
|
(defn text-input [{:keys [font style] :as opts
|
|
:or {font :default}} text]
|
|
(let [font (get-in platform-specific [:fonts (keyword font)])]
|
|
[text-input-class (merge
|
|
{:underline-color-android :transparent
|
|
:placeholder-text-color st/text2-color
|
|
:placeholder (i18n/label :t/type-a-message)
|
|
:value text}
|
|
(-> opts
|
|
(dissoc :font)
|
|
(assoc :style (merge style font))))]))
|
|
|
|
(defn icon
|
|
([n] (icon n st/icon-default))
|
|
([n style]
|
|
[image {:source {:uri (keyword (str "icon_" (name n)))}
|
|
:resizeMode "contain"
|
|
:style style}]))
|
|
|
|
(defn touchable-highlight [props content]
|
|
[touchable-highlight-class
|
|
(merge {:underlay-color :transparent} props)
|
|
content])
|
|
|
|
(defn get-dimensions [name]
|
|
(js->clj (.get dimensions name) :keywordize-keys true))
|
|
|
|
(def gradient (adapt-class (.-default rn-dependencies/linear-gradient)))
|
|
|
|
(defn linear-gradient [props]
|
|
[gradient props])
|
|
|
|
(defn list-item [component]
|
|
(r/as-element component))
|
|
|
|
(defn picker
|
|
([{:keys [style item-style selected on-change]} items]
|
|
[picker-class {:selectedValue selected :style style :itemStyle item-style :onValueChange on-change}
|
|
(for [{:keys [label value]} items]
|
|
^{:key (str value)}
|
|
[picker-item-class
|
|
{:label (or label value) :value value}])]))
|
|
|
|
;; Image picker
|
|
|
|
(def image-picker-class rn-dependencies/image-crop-picker)
|
|
|
|
(defn show-access-error [o]
|
|
(when (= "ERROR_PICKER_UNAUTHORIZED_KEY" (aget o "code")) ; Do not show error when user cancel selection
|
|
(u/show-popup (i18n/label :t/error)
|
|
(i18n/label :t/photos-access-error))))
|
|
|
|
(defn show-image-picker [images-fn]
|
|
(let [image-picker (.-default image-picker-class)]
|
|
(-> image-picker
|
|
(.openPicker (clj->js {:multiple false}))
|
|
(.then images-fn)
|
|
(.catch show-access-error))))
|
|
|
|
(def swiper (adapt-class rn-dependencies/swiper))
|
|
|
|
;; Clipboard
|
|
|
|
(def sharing
|
|
(.-Share rn-dependencies/react-native))
|
|
|
|
(defn copy-to-clipboard [text]
|
|
(.setString (.-Clipboard rn-dependencies/react-native) text))
|
|
|
|
(defn get-from-clipboard [clbk]
|
|
(let [clipboard-contents (.getString (.-Clipboard rn-dependencies/react-native))]
|
|
(.then clipboard-contents #(clbk %))))
|
|
|
|
|
|
;; Emoji
|
|
|
|
(def emoji-picker-class rn-dependencies/emoji-picker)
|
|
|
|
(def emoji-picker
|
|
(let [emoji-picker (.-default emoji-picker-class)]
|
|
(r/adapt-react-class emoji-picker)))
|
|
|
|
;; Autolink
|
|
|
|
(def autolink-class (r/adapt-react-class (.-default rn-dependencies/autolink)))
|
|
|
|
(defn autolink [opts]
|
|
(r/as-element
|
|
[autolink-class (add-font-style :style opts)]))
|
|
|
|
;; HTTP Bridge
|
|
|
|
(def http-bridge rn-dependencies/http-bridge)
|
|
|
|
;; KeyboardAvoidingView
|
|
|
|
(defn keyboard-avoiding-view [props & children]
|
|
(let [view-element (if ios?
|
|
[keyboard-avoiding-view-class (merge {:behavior :padding} props)]
|
|
[view props])]
|
|
(vec (concat view-element children))))
|
|
|
|
(views/defview with-activity-indicator [{:keys [timeout style enabled?]} comp]
|
|
(views/letsubs
|
|
[loading (r/atom true)]
|
|
{:component-did-mount (fn []
|
|
(if (or (nil? timeout)
|
|
(> 100 timeout))
|
|
(reset! loading false)
|
|
(js/setTimeout (fn []
|
|
(reset! loading false))
|
|
timeout)))}
|
|
(if (and (not enabled?) @loading)
|
|
[view {:style style}
|
|
[activity-indicator {:animating true}]]
|
|
comp)))
|