[Fix #3252] Remove dependency on react-native-autolink

Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
Foo Pang 2018-02-13 14:33:26 +08:00 committed by Julien Eluard
parent 6bde9828cb
commit c1900a24ec
No known key found for this signature in database
GPG Key ID: 6FD7DB5437FCBEF6
11 changed files with 100 additions and 60 deletions

View File

@ -37,7 +37,6 @@
"web3", "web3",
"eccjs", "eccjs",
"chance", "chance",
"react-native-autolink",
"instabug-reactnative", "instabug-reactnative",
"nfc-react-native", "nfc-react-native",
"react-native-http-bridge", "react-native-http-bridge",

14
package-lock.json generated
View File

@ -401,11 +401,6 @@
"resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz",
"integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=" "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10="
}, },
"autolinker": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.6.0.tgz",
"integrity": "sha1-utN2t62OQV8i8QL8Dzf2QOZPHL8="
},
"aws-sign2": { "aws-sign2": {
"version": "0.7.0", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
@ -6882,15 +6877,6 @@
"prop-types": "15.6.0" "prop-types": "15.6.0"
} }
}, },
"react-native-autolink": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/react-native-autolink/-/react-native-autolink-1.1.1.tgz",
"integrity": "sha512-h11oWD1x0Z1ar0W493tpXJ8hMofpcm21xg3wPFIy5r4CvsRlWNMBp9iG+4jeYqCNAQcDHHeu5yO+NJVaWffXZg==",
"requires": {
"autolinker": "1.6.0",
"prop-types": "15.6.0"
}
},
"react-native-background-timer": { "react-native-background-timer": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-native-background-timer/-/react-native-background-timer-2.0.0.tgz", "resolved": "https://registry.npmjs.org/react-native-background-timer/-/react-native-background-timer-2.0.0.tgz",

View File

@ -47,7 +47,6 @@
"react-dom": "16.2.0", "react-dom": "16.2.0",
"react-native": "0.51.0", "react-native": "0.51.0",
"react-native-action-button": "2.8.1", "react-native-action-button": "2.8.1",
"react-native-autolink": "1.1.1",
"react-native-background-timer": "2.0.0", "react-native-background-timer": "2.0.0",
"react-native-camera": "0.10.0", "react-native-camera": "0.10.0",
"react-native-config": "0.9.0", "react-native-config": "0.9.0",

View File

@ -1,7 +1,6 @@
(ns status-im.react-native.js-dependencies) (ns status-im.react-native.js-dependencies)
(def action-button (js/require "react-native-action-button")) (def action-button (js/require "react-native-action-button"))
(def autolink (js/require "react-native-autolink"))
(def camera (js/require "react-native-camera")) (def camera (js/require "react-native-camera"))
(def config (js/require "react-native-config")) (def config (js/require "react-native-config"))
(def dialogs (js/require "react-native-dialogs")) (def dialogs (js/require "react-native-dialogs"))

View File

@ -14,10 +14,12 @@
[status-im.chat.views.message.request-message :as request-message] [status-im.chat.views.message.request-message :as request-message]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen] [status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.utils.core :as utils]
[status-im.utils.identicon :as identicon] [status-im.utils.identicon :as identicon]
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[clojure.string :as string] [clojure.string :as string]
[status-im.chat.events.console :as console] [status-im.chat.events.console :as console]
[taoensso.timbre :as log])) [taoensso.timbre :as log]))
@ -65,7 +67,7 @@
(defview message-content-command (defview message-content-command
[{:keys [content params] :as message}] [{:keys [content params] :as message}]
(letsubs [command [:get-command (:content-command-ref content)]] (letsubs [command [:get-command (:content-command-ref content)]]
(let [preview (:preview content) (let [preview (:preview content)
{:keys [type color] icon-path :icon} command] {:keys [type color] icon-path :icon} command]
[react/view style/content-command-view [react/view style/content-command-view
@ -96,7 +98,49 @@
{"\\*[^*]+\\*" {:font-weight :bold} {"\\*[^*]+\\*" {:font-weight :bold}
"~[^~]+~" {:font-style :italic}}) "~[^~]+~" {:font-style :italic}})
(def regx (re-pattern (string/join "|" (map first replacements)))) (def regx-styled (re-pattern (string/join "|" (map first replacements))))
(def regx-url #"(?i)(?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{1,4}/?)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'\".,<>?«»“”‘’]){0,}")
(defn- parse-str-regx [string regx matched-fn unmatched-fn]
(if (string? string)
(let [unmatched-text (as-> (->> (string/split string regx)
(remove empty?)
vec) $
(if (zero? (count $))
[nil]
(unmatched-fn $)))
matched-text (as-> (->> string
(re-seq regx)
matched-fn
vec) $
(if (> (count unmatched-text)
(count $))
(conj $ nil)
$))]
(mapcat vector unmatched-text matched-text))
(str string)))
(defn parse-url [string]
(parse-str-regx string
regx-url
(fn [text-seq]
(map (fn [[text]] {:text text :url? true}) text-seq))
(fn [text-seq]
(map (fn [text] {:text text :url? false}) text-seq))))
(defn- autolink [string on-press]
(->> (parse-url string)
(map-indexed (fn [idx {:keys [text url?]}]
(if url?
(let [[url _ _ _ text] (re-matches #"(?i)^((\w+://)?(www\d{0,3}[.])?)?(.*)$" text)]
[react/text
{:key idx
:style {:color colors/blue}
:on-press #(on-press url)}
(utils/truncate-str text 32 true)])
text)))
vec))
(defn get-style [string] (defn get-style [string]
(->> replacements (->> replacements
@ -108,37 +152,29 @@
replacements)) replacements))
;; todo rewrite this, naive implementation ;; todo rewrite this, naive implementation
(defn- parse-text [string] (defn- parse-text [string url-on-press]
(if (string? string) (parse-str-regx string
(let [general-text (string/split string regx) regx-styled
general-text' (if (zero? (count general-text)) (fn [text-seq]
[nil] (map-indexed (fn [idx string]
general-text) (let [style (get-style string)]
styled-text (vec (map-indexed (fn [idx string] [react/text
(let [style (get-style string)] {:key (str idx "_" string)
[react/text :style style}
{:key (str idx "_" string) (subs string 1 (dec (count string)))]))
:style style} text-seq))
(subs string 1 (dec (count string)))])) (fn [text-seq]
(re-seq regx string))) (map-indexed (fn [idx string]
styled-text' (if (> (count general-text) (apply react/text
(count styled-text)) {:key (str idx "_" string)}
(conj styled-text nil) (autolink string url-on-press)))
styled-text)] text-seq))))
(mapcat vector general-text' styled-text'))
(str string)))
(defn text-message (defn text-message
[{:keys [content] :as message}] [{:keys [content] :as message}]
[message-view message [message-view message
(let [parsed-text (parse-text content) (let [parsed-text (parse-text content #(re-frame/dispatch [:browse-link-from-message %]))]
simple-text? (and (= (count parsed-text) 2) [react/text {:style (style/text-message message)} parsed-text])])
(nil? (second parsed-text)))]
(if simple-text?
[react/autolink {:style (style/text-message message)
:text (apply str parsed-text)
:onPress #(re-frame/dispatch [:browse-link-from-message %])}]
[react/text {:style (style/text-message message)} parsed-text]))])
(defmulti message-content (fn [_ message _] (message :content-type))) (defmulti message-content (fn [_ message _] (message :content-type)))

View File

@ -160,15 +160,6 @@
(let [clipboard-contents (.getString (.-Clipboard js-dependencies/react-native))] (let [clipboard-contents (.getString (.-Clipboard js-dependencies/react-native))]
(.then clipboard-contents #(clbk %)))) (.then clipboard-contents #(clbk %))))
;; Autolink
(def autolink-class (reagent/adapt-react-class (.-default js-dependencies/autolink)))
(defn autolink [opts]
(reagent/as-element
[autolink-class (add-font-style :style opts)]))
;; HTTP Bridge ;; HTTP Bridge
(def http-bridge js-dependencies/http-bridge) (def http-bridge js-dependencies/http-bridge)

View File

@ -3,11 +3,19 @@
(defn truncate-str (defn truncate-str
"Given string and max threshold, trims the string to threshold length with `...` "Given string and max threshold, trims the string to threshold length with `...`
appended to end if length of the string exceeds max threshold, returns the same appended to end or in the middle if length of the string exceeds max threshold,
string if threshold is not exceeded" returns the same string if threshold is not exceeded"
[s threshold] [s threshold & [middle?]]
(if (and s (< threshold (count s))) (if (and s (< threshold (count s)))
(str (subs s 0 (- threshold 3)) "...") (if middle?
(let [str-len (count s)
max-len (- threshold 3)
start-len (Math/ceil (/ max-len 2))
end-len (Math/floor (/ max-len 2))
start (subs s 0 start-len)
end (subs s (- str-len end-len) str-len)]
(str start "..." end))
(str (subs s 0 (- threshold 3)) "..."))
s)) s))
(defn clean-text [s] (defn clean-text [s]

View File

@ -1,7 +1,6 @@
(ns status-im.react-native.js-dependencies) (ns status-im.react-native.js-dependencies)
(def action-button #js {:default #js {:Item #js {}}}) (def action-button #js {:default #js {:Item #js {}}})
(def autolink #js {:default #js {}})
(def config #js {:default #js {}}) (def config #js {:default #js {}})
(def camera #js {:constants #js {}}) (def camera #js {:constants #js {}})
(def dialogs #js {}) (def dialogs #js {})

View File

@ -0,0 +1,20 @@
(ns status-im.test.chat.views.message
(:require [cljs.test :refer [deftest is]]
[status-im.chat.views.message.message :as message]))
(deftest parse-url
(is (= (lazy-seq [nil {:text "www.google.com" :url? true}])
(message/parse-url "www.google.com")))
(is (= (lazy-seq [nil {:text "status.im" :url? true}])
(message/parse-url "status.im")))
(is (= (lazy-seq [{:text "$33.90" :url? false} nil])
(message/parse-url "$33.90")))
(is (= (lazy-seq [nil {:text "https://www.google.com/?gfe_rd=cr&dcr=0&ei=P9-CWuyBGaro8AeqkYGQDQ&gws_rd=cr&fg=1" :url? true}])
(message/parse-url "https://www.google.com/?gfe_rd=cr&dcr=0&ei=P9-CWuyBGaro8AeqkYGQDQ&gws_rd=cr&fg=1")))
(is (= (lazy-seq [{:text "Status - " :url? false}
{:text "https://github.com/status-im/status-react" :url? true}
{:text " a Mobile Ethereum Operating System" :url? false}
nil])
(message/parse-url "Status - https://github.com/status-im/status-react a Mobile Ethereum Operating System")))
(is (= (lazy-seq [{:text "Browse, chat and make payments securely on the decentralized web." :url? false} nil])
(message/parse-url "Browse, chat and make payments securely on the decentralized web."))))

View File

@ -9,6 +9,7 @@
[status-im.test.profile.events] [status-im.test.profile.events]
[status-im.test.bots.events] [status-im.test.bots.events]
[status-im.test.chat.models.input] [status-im.test.chat.models.input]
[status-im.test.chat.views.message]
[status-im.test.i18n] [status-im.test.i18n]
[status-im.test.protocol.web3.inbox] [status-im.test.protocol.web3.inbox]
[status-im.test.utils.utils] [status-im.test.utils.utils]
@ -43,6 +44,7 @@
'status-im.test.wallet.transactions.subs 'status-im.test.wallet.transactions.subs
'status-im.test.wallet.transactions.views 'status-im.test.wallet.transactions.views
'status-im.test.chat.models.input 'status-im.test.chat.models.input
'status-im.test.chat.views.message
'status-im.test.i18n 'status-im.test.i18n
'status-im.test.protocol.web3.inbox 'status-im.test.protocol.web3.inbox
'status-im.test.utils.utils 'status-im.test.utils.utils

View File

@ -13,6 +13,7 @@
(deftest truncate-str-test (deftest truncate-str-test
(is (= (u/truncate-str "Long string" 7) "Long...")) ; threshold is less then string length (is (= (u/truncate-str "Long string" 7) "Long...")) ; threshold is less then string length
(is (= (u/truncate-str "Long string" 7 true) "Lo...ng")) ; threshold is less then string length (truncate middle)
(is (= (u/truncate-str "Long string" 11) "Long string")) ; threshold is the same as string length (is (= (u/truncate-str "Long string" 11) "Long string")) ; threshold is the same as string length
(is (= (u/truncate-str "Long string" 20) "Long string"))) ; threshold is more then string length (is (= (u/truncate-str "Long string" 20) "Long string"))) ; threshold is more then string length