Skip to content

Commit 1e4a49f

Browse files
authored
Integrate support for SVG icons and fix clear icon (#15691)
This commit solves the problem described in detail in issue #15606, but in essence, it fixes the clear icon by integrating rudimentary support for SVG icons. Fixes #15606 - Hopefully, if SVG icons prove to be a solid solution, we can easily and progressively migrate PNG icons to SVGs, but for the moment, it was aligned with @flexsurfer #15606 (comment) that we'll only use SVG icons on demand. - Note that it's possible to import SVGs directly via js/require by installing the library react-native-svg-transformer, but this approach is only good when we don't want/need color customization, which is rarely the case with icons where we want to change the foreground and/or background colors. I opted for rendering the SVG icon as hiccup to support color customization. - Since icons are fully memoized, the app's performance is on the same ballpark as PNGs rendered with RN Image. - It's possible to trim down SVGs by using a tool such as https://github.com/svg/svgo, but this is obviously outside the scope of this PR.
1 parent faa29a2 commit 1e4a49f

File tree

11 files changed

+92
-38
lines changed

11 files changed

+92
-38
lines changed

src/mocks/js_dependencies.cljs

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
141141
{:ClipPath #js {:render identity}
142142
:Circle #js {:render identity}
143143
:Defs #js {:render identity}
144+
:G #js {:render identity}
144145
:Path #js {:render identity}
145146
:Rect #js {:render identity}
146147
:SvgUri #js {:render identity}

src/quo2/components/icon.cljs

+27-13
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,43 @@
11
(ns quo2.components.icon
22
(:require [clojure.string :as string]
33
[quo2.components.icons.icons :as icons]
4+
[quo2.components.icons.svg :as icons.svg]
45
[quo2.foundations.colors :as colors]
56
[react-native.core :as rn]))
67

8+
(defn- valid-color?
9+
[color]
10+
(or (keyword? color)
11+
(and (string? color)
12+
(not (string/blank? color)))))
13+
714
(defn memo-icon-fn
815
([icon-name] (memo-icon-fn icon-name nil))
916
([icon-name
10-
{:keys [color container-style size
11-
accessibility-label no-color]
17+
{:keys [color color-2 no-color
18+
container-style size accessibility-label]
1219
:or {accessibility-label :icon}}]
1320
(let [size (or size 20)]
1421
^{:key icon-name}
15-
[rn/image
16-
{:style
17-
(merge {:width size
18-
:height size}
22+
(if-let [svg-icon (icons.svg/get-icon icon-name size)]
23+
[svg-icon
24+
{:size size
25+
:color (when (valid-color? color) color)
26+
:color-2 (when (valid-color? color-2) color-2)
27+
:accessibility-label accessibility-label
28+
:style container-style}]
29+
[rn/image
30+
{:style
31+
(merge {:width size
32+
:height size}
1933

20-
(when (not no-color)
21-
{:tint-color (if (and (string? color) (not (string/blank? color)))
22-
color
23-
(colors/theme-colors colors/neutral-100 colors/white))})
34+
(when (not no-color)
35+
{:tint-color (if (and (string? color) (not (string/blank? color)))
36+
color
37+
(colors/theme-colors colors/neutral-100 colors/white))})
2438

25-
container-style)
26-
:accessibility-label accessibility-label
27-
:source (icons/icon-source (str (name icon-name) size))}])))
39+
container-style)
40+
:accessibility-label accessibility-label
41+
:source (icons/icon-source (str (name icon-name) size))}]))))
2842

2943
(def icon (memoize memo-icon-fn))

src/quo2/components/icons/icons.clj

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
(:require [clojure.java.io :as io]
33
[clojure.string :as string]))
44

5-
(def icon-path "./resources/images/icons2/")
5+
(def ^:private icon-path "./resources/images/icons2/")
66

7-
(defn require-icon
7+
(defn- require-icon
88
[size path]
99
(fn [el]
1010
(let [s (str "." path el ".png")
@@ -15,15 +15,15 @@
1515
(str size))]
1616
[k `(js/require ~s)])))
1717

18-
(defn get-files
18+
(defn- get-files
1919
[path]
2020
(->> (io/file path)
2121
file-seq
2222
(filter #(string/ends-with? % "png"))
2323
(map #(first (string/split (.getName %) #"@")))
2424
distinct))
2525

26-
(defn get-icons
26+
(defn- get-icons
2727
[size]
2828
(let [path (str icon-path size "x" size "/")]
2929
(into {} (map (require-icon size path) (get-files path)))))

src/quo2/components/icons/icons.cljs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
(:require-macros [quo2.components.icons.icons :as icons])
33
(:require [taoensso.timbre :as log]))
44

5-
(def icons (icons/resolve-icons))
5+
(def ^:private icons (icons/resolve-icons))
66

77
(defn icon-source
88
[icon]

src/quo2/components/icons/svg.cljs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
(ns quo2.components.icons.svg
2+
"Declare icons in this namespace when they have two possible colors, because the
3+
ReactNative `:tint-color` prop affects all non-transparent pixels of PNGs. If
4+
the icon has only one color, prefer a PNG.
5+
6+
Keep all SVG components private and expose them by name in the `icons` var."
7+
(:require [react-native.svg :as svg]
8+
[quo2.foundations.colors :as colors]))
9+
10+
(defn- container
11+
[{:keys [size accessibility-label style]
12+
:or {size 20}}
13+
& children]
14+
(into [svg/svg
15+
{:accessibility-label accessibility-label
16+
:style style
17+
:width size
18+
:height size
19+
:view-box (str "0 0 " size " " size)
20+
:fill :none}]
21+
children))
22+
23+
(defn- clear-20
24+
[{:keys [color color-2] :as props}]
25+
(let [color (or color colors/neutral-100)
26+
color-2 (or color-2 colors/white)]
27+
[container props
28+
[svg/path
29+
{:d
30+
"M3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10Z"
31+
:fill color}]
32+
[svg/path
33+
{:d
34+
"M9.15142 9.99998L7.07566 12.0757L7.9242 12.9243L9.99994 10.8485L12.0757 12.9242L12.9242 12.0757L10.8485 9.99998L12.9242 7.92421L12.0757 7.07568L9.99994 9.15145L7.92421 7.07572L7.07568 7.92425L9.15142 9.99998Z"
35+
:fill color-2}]]))
36+
37+
(def ^:private icons
38+
{:i/clear-20 clear-20})
39+
40+
(defn- append-to-keyword
41+
[k & xs]
42+
(keyword (apply str
43+
(subs (str k) 1)
44+
xs)))
45+
46+
(defn get-icon
47+
[icon-name size]
48+
(get icons (append-to-keyword icon-name "-" size)))

src/quo2/components/inputs/search_input/style.cljs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
[blur? override-theme]
2929
(if blur?
3030
(colors/theme-colors colors/neutral-80-opa-30 colors/white-opa-10 override-theme)
31-
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
31+
(colors/theme-colors colors/neutral-40 colors/neutral-60 override-theme)))
3232

3333
(defn cursor
3434
[customization-color override-theme]

src/quo2/components/links/url_preview/style.cljs

-4
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,6 @@
4848
{:text-transform :lowercase
4949
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)})
5050

51-
(def clear-button
52-
{:border-color colors/danger-50
53-
:border-width 1})
54-
5551
(def clear-button-container
5652
{:width 20
5753
:height 20

src/quo2/components/links/url_preview/view.cljs

+2-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@
3939
:hit-slop {:top 3 :right 3 :bottom 3 :left 3}
4040
:accessibility-label :button-clear-preview}
4141
[icon/icon :i/clear
42-
{:size 20
43-
:container-style style/clear-button
44-
:color (colors/theme-colors colors/neutral-50 colors/neutral-60)}]])
42+
{:size 20
43+
:color (colors/theme-colors colors/neutral-50 colors/neutral-60)}]])
4544

4645
(defn view
4746
[{:keys [title body logo on-clear loading? loading-message container-style]}]

src/react_native/svg.cljs

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
(def defs (reagent/adapt-react-class Svg/Defs))
1010
(def circle (reagent/adapt-react-class Svg/Circle))
1111
(def svgxml (reagent/adapt-react-class Svg/SvgXml))
12+
(def g (reagent/adapt-react-class Svg/G))

src/status_im/ui2/screens/chat/composer/images/style.cljs

+4-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
(ns status-im.ui2.screens.chat.composer.images.style
2-
(:require [quo2.foundations.colors :as colors]))
1+
(ns status-im.ui2.screens.chat.composer.images.style)
32

43
(def remove-photo-container
5-
{:width 14
6-
:height 14
7-
:border-radius 7
8-
:background-color colors/neutral-50
9-
:position :absolute
10-
:top 5
11-
:right 5
12-
:justify-content :center
13-
:align-items :center})
4+
{:position :absolute
5+
:top 5
6+
:right 5})
147

158
(def small-image
169
{:width 56

src/status_im/ui2/screens/chat/composer/images/view.cljs

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
:left 5
2121
:top 10
2222
:bottom 10}}
23-
[quo/icon :i/close {:color colors/white :size 12}]]])
23+
[quo/icon :i/clear
24+
{:size 20
25+
:color (colors/theme-colors colors/neutral-50 colors/neutral-60)}]]])
2426

2527
(defn images-list
2628
[images]

0 commit comments

Comments
 (0)