[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",
"eccjs",
"chance",
"react-native-autolink",
"instabug-reactnative",
"nfc-react-native",
"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",
"integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10="
},
"autolinker": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.6.0.tgz",
"integrity": "sha1-utN2t62OQV8i8QL8Dzf2QOZPHL8="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
@ -6882,15 +6877,6 @@
"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": {
"version": "2.0.0",
"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-native": "0.51.0",
"react-native-action-button": "2.8.1",
"react-native-autolink": "1.1.1",
"react-native-background-timer": "2.0.0",
"react-native-camera": "0.10.0",
"react-native-config": "0.9.0",

View File

@ -1,7 +1,6 @@
(ns status-im.react-native.js-dependencies)
(def action-button (js/require "react-native-action-button"))
(def autolink (js/require "react-native-autolink"))
(def camera (js/require "react-native-camera"))
(def config (js/require "react-native-config"))
(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.constants :as constants]
[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.gfycat.core :as gfycat]
[status-im.utils.platform :as platform]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[clojure.string :as string]
[status-im.chat.events.console :as console]
[taoensso.timbre :as log]))
@ -65,7 +67,7 @@
(defview message-content-command
[{: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)
{:keys [type color] icon-path :icon} command]
[react/view style/content-command-view
@ -96,7 +98,49 @@
{"\\*[^*]+\\*" {:font-weight :bold}
"~[^~]+~" {: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]
(->> replacements
@ -108,37 +152,29 @@
replacements))
;; todo rewrite this, naive implementation
(defn- parse-text [string]
(if (string? string)
(let [general-text (string/split string regx)
general-text' (if (zero? (count general-text))
[nil]
general-text)
styled-text (vec (map-indexed (fn [idx string]
(let [style (get-style string)]
[react/text
{:key (str idx "_" string)
:style style}
(subs string 1 (dec (count string)))]))
(re-seq regx string)))
styled-text' (if (> (count general-text)
(count styled-text))
(conj styled-text nil)
styled-text)]
(mapcat vector general-text' styled-text'))
(str string)))
(defn- parse-text [string url-on-press]
(parse-str-regx string
regx-styled
(fn [text-seq]
(map-indexed (fn [idx string]
(let [style (get-style string)]
[react/text
{:key (str idx "_" string)
:style style}
(subs string 1 (dec (count string)))]))
text-seq))
(fn [text-seq]
(map-indexed (fn [idx string]
(apply react/text
{:key (str idx "_" string)}
(autolink string url-on-press)))
text-seq))))
(defn text-message
[{:keys [content] :as message}]
[message-view message
(let [parsed-text (parse-text content)
simple-text? (and (= (count parsed-text) 2)
(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]))])
(let [parsed-text (parse-text content #(re-frame/dispatch [:browse-link-from-message %]))]
[react/text {:style (style/text-message message)} parsed-text])])
(defmulti message-content (fn [_ message _] (message :content-type)))

View File

@ -160,15 +160,6 @@
(let [clipboard-contents (.getString (.-Clipboard js-dependencies/react-native))]
(.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
(def http-bridge js-dependencies/http-bridge)

View File

@ -3,11 +3,19 @@
(defn truncate-str
"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
string if threshold is not exceeded"
[s threshold]
appended to end or in the middle if length of the string exceeds max threshold,
returns the same string if threshold is not exceeded"
[s threshold & [middle?]]
(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))
(defn clean-text [s]

View File

@ -1,7 +1,6 @@
(ns status-im.react-native.js-dependencies)
(def action-button #js {:default #js {:Item #js {}}})
(def autolink #js {:default #js {}})
(def config #js {:default #js {}})
(def camera #js {:constants #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.bots.events]
[status-im.test.chat.models.input]
[status-im.test.chat.views.message]
[status-im.test.i18n]
[status-im.test.protocol.web3.inbox]
[status-im.test.utils.utils]
@ -43,6 +44,7 @@
'status-im.test.wallet.transactions.subs
'status-im.test.wallet.transactions.views
'status-im.test.chat.models.input
'status-im.test.chat.views.message
'status-im.test.i18n
'status-im.test.protocol.web3.inbox
'status-im.test.utils.utils

View File

@ -13,6 +13,7 @@
(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 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" 20) "Long string"))) ; threshold is more then string length