Skip to content

Commit 9955f88

Browse files
authored
Merge branch 'develop' into mute-for-specific-amount-of-time
2 parents 919e607 + a46a3e2 commit 9955f88

File tree

13 files changed

+443
-178
lines changed

13 files changed

+443
-178
lines changed

nix/overlay.nix

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ in {
5353
version = "13.3";
5454
allowHigher = true;
5555
};
56-
go = super.go_1_18;
57-
buildGoPackage = super.buildGo118Package;
58-
buildGoModule = super.buildGo118Module;
56+
go = super.go_1_19;
57+
buildGoPackage = super.buildGo119Package;
58+
buildGoModule = super.buildGo119Module;
5959
gomobile = (super.gomobile.overrideAttrs (old: {
6060
patches = self.fetchurl { # https://github.com/golang/mobile/pull/84
6161
url = "https://github.com/golang/mobile/commit/f20e966e05b8f7e06bed500fa0da81cf6ebca307.patch";
+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
(ns quo2.components.code.code.style
2+
(:require [quo2.foundations.colors :as colors]))
3+
4+
;; Example themes:
5+
;; https://github.com/react-syntax-highlighter/react-syntax-highlighter/tree/master/src/styles/hljs
6+
(defn theme
7+
[theme-key]
8+
(case theme-key
9+
:hljs-comment (colors/theme-colors colors/neutral-40 colors/neutral-60)
10+
:hljs-title (colors/custom-color-by-theme :sky 50 60)
11+
:hljs-keyword (colors/custom-color-by-theme :green 50 60)
12+
:hljs-string (colors/custom-color-by-theme :turquoise 50 60)
13+
:hljs-literal (colors/custom-color-by-theme :turquoise 50 60)
14+
:hljs-number (colors/custom-color-by-theme :turquoise 50 60)
15+
:line-number colors/neutral-40
16+
nil))
17+
18+
(defn text-style
19+
[class-names]
20+
(let [text-color (->> class-names
21+
(map keyword)
22+
(some (fn [class-name]
23+
(when-let [text-color (theme class-name)]
24+
text-color))))]
25+
(cond-> {:flex-shrink 1
26+
:line-height 18}
27+
text-color (assoc :color text-color))))
28+
29+
(defn border-color
30+
[]
31+
(colors/theme-colors colors/neutral-20 colors/neutral-80))
32+
33+
(defn container
34+
[]
35+
{:overflow :hidden
36+
:padding 8
37+
:background-color (colors/theme-colors colors/white colors/neutral-80-opa-40)
38+
:border-color (border-color)
39+
:border-width 1
40+
:border-radius 16})
41+
42+
(def gradient-container
43+
{:position :absolute
44+
:bottom 0
45+
:left 0
46+
:right 0
47+
:z-index 1})
48+
49+
(def gradient {:height 48})
50+
51+
(defn line-number-container
52+
[line-number-width]
53+
{:position :absolute
54+
:bottom 0
55+
:top 0
56+
:left 0
57+
:width (+ line-number-width 8 7)
58+
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80)})
59+
60+
(defn divider
61+
[line-number-width]
62+
{:position :absolute
63+
:bottom 0
64+
:top 0
65+
:left (+ line-number-width 7 7)
66+
:width 1
67+
:z-index 2
68+
:background-color (border-color)})
69+
70+
(def line {:flex-direction :row})
71+
72+
(defn line-number
73+
[width]
74+
{:margin-right 20 ; 8+12 margin
75+
:width width})
76+
77+
(def copy-button
78+
{:position :absolute
79+
:bottom 8
80+
:right 8
81+
:z-index 1})
82+
83+
(defn gradient-color [] (colors/theme-colors colors/white colors/neutral-80))
84+
85+
(defn button-background-color
86+
[]
87+
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5))

src/quo2/components/code/snippet.cljs

+78-143
Original file line numberDiff line numberDiff line change
@@ -1,175 +1,110 @@
11
(ns quo2.components.code.snippet
22
(:require [cljs-bean.core :as bean]
33
[clojure.string :as string]
4-
[oops.core :as oops]
54
[quo2.components.buttons.button :as button]
5+
[quo2.components.code.code.style :as style]
66
[quo2.components.markdown.text :as text]
7-
[quo2.foundations.colors :as colors]
8-
[quo2.theme :as theme]
97
[react-native.core :as rn]
108
[react-native.linear-gradient :as linear-gradient]
11-
[react-native.masked-view :as masked-view]
129
[react-native.syntax-highlighter :as highlighter]
1310
[reagent.core :as reagent]))
1411

15-
;; Example themes:
16-
;; https://github.com/react-syntax-highlighter/react-syntax-highlighter/tree/master/src/styles/hljs
17-
(def ^:private themes
18-
{:light {:hljs-comment {:color colors/neutral-40}
19-
:hljs-title {:color (colors/custom-color :blue 50)}
20-
:hljs-keyword {:color (colors/custom-color :green 50)}
21-
:hljs-string {:color (colors/custom-color :turquoise 50)}
22-
:hljs-literal {:color (colors/custom-color :turquoise 50)}
23-
:hljs-number {:color (colors/custom-color :turquoise 50)}
24-
:line-number {:color colors/neutral-40}}
25-
:dark {:hljs-comment {:color colors/neutral-60}
26-
:hljs-title {:color (colors/custom-color :blue 60)}
27-
:hljs-keyword {:color (colors/custom-color :green 60)}
28-
:hljs-string {:color (colors/custom-color :turquoise 60)}
29-
:hljs-literal {:color (colors/custom-color :turquoise 60)}
30-
:hljs-number {:color (colors/custom-color :turquoise 60)}
31-
:line-number {:color colors/neutral-40}}})
32-
33-
(defn- text-style
34-
[class-names]
35-
(->> class-names
36-
(map keyword)
37-
(reduce #(merge %1 (get-in themes [(theme/get-theme) %2]))
38-
{:flex-shrink 1
39-
;; Round to a nearest whole number to achieve consistent
40-
;; spacing (also important for calculating `max-text-height`).
41-
;; Line height seems to be inconsistent between text being
42-
;; wrapped and text being rendered on a newline using Flexbox
43-
;; layout.
44-
:line-height 18})))
45-
4612
(defn- render-nodes
4713
[nodes]
48-
(map (fn [{:keys [children value] :as node}]
49-
;; Node can have :children or a :value.
14+
(map (fn [{:keys [children value last-line?] :as node}]
5015
(if children
5116
(into [text/text
52-
{:weight :code
53-
:size :paragraph-2
54-
:style (text-style (get-in node [:properties :className]))}]
17+
(cond-> {:weight :code
18+
:size :paragraph-2
19+
:style (style/text-style (get-in node [:properties :className]))}
20+
last-line? (assoc :number-of-lines 1))]
5521
(render-nodes children))
5622
;; Remove newlines as we already render each line separately.
57-
(-> value string/trim-newline)))
23+
(string/trim-newline value)))
5824
nodes))
5925

26+
(defn- line
27+
[{:keys [line-number line-number-width]} children]
28+
[rn/view {:style style/line}
29+
[rn/view {:style (style/line-number line-number-width)}
30+
[text/text
31+
{:style (style/text-style ["line-number"])
32+
:weight :code
33+
:size :paragraph-2}
34+
line-number]]
35+
children])
36+
6037
(defn- code-block
6138
[{:keys [rows line-number-width]}]
62-
[into [:<>]
39+
[rn/view
6340
(->> rows
6441
(render-nodes)
65-
;; Line numbers
66-
(map-indexed (fn [idx row]
67-
(conj [rn/view {:style {:flex-direction :row}}
68-
[rn/view
69-
{:style {:width line-number-width
70-
;; 8+12 margin
71-
:margin-right 20}}
72-
[text/text
73-
{:weight :code
74-
:size :paragraph-2
75-
:style (text-style ["line-number"])}
76-
(inc idx)]]]
77-
row))))])
42+
(map-indexed (fn [idx row-content]
43+
[line
44+
{:line-number (inc idx)
45+
:line-number-width line-number-width}
46+
row-content]))
47+
(into [:<>]))])
7848

79-
(defn- native-renderer
80-
[]
81-
(let [text-height (reagent/atom nil)]
82-
(fn [{:keys [rows max-lines on-copy-press]}]
83-
(let [background-color (colors/theme-colors
84-
colors/white
85-
colors/neutral-80-opa-40)
86-
background-color-left (colors/theme-colors
87-
colors/neutral-5
88-
colors/neutral-80)
89-
border-color (colors/theme-colors
90-
colors/neutral-20
91-
colors/neutral-80)
92-
rows (bean/->clj rows)
93-
font-scale (:font-scale (rn/use-window-dimensions))
94-
max-rows (or max-lines (count rows)) ;; Cut down on rows to process.
95-
max-line-digits (-> rows count (min max-rows) str count)
96-
;; ~ 9 is char width, 18 is width used in Figma.
97-
line-number-width (* font-scale (max 18 (* 9 max-line-digits)))
98-
max-text-height (some-> max-lines
99-
(* font-scale 18)) ;; 18 is font's line height.
100-
truncated? (and max-text-height (< max-text-height @text-height))
101-
maybe-mask-wrapper (if truncated?
102-
[masked-view/masked-view
103-
{:mask-element
104-
(reagent/as-element
105-
[linear-gradient/linear-gradient
106-
{:colors ["black" "transparent"]
107-
:locations [0.75 1]
108-
:style {:flex 1}}])}]
109-
[:<>])]
110-
111-
[rn/view
112-
{:style {:overflow :hidden
113-
:padding 8
114-
:background-color background-color
115-
:border-color border-color
116-
:border-width 1
117-
:border-radius 8
118-
;; Hide on intial render to avoid flicker when mask-wrapper is shown.
119-
:opacity (if @text-height 1 0)}}
120-
;; Line number container
121-
[rn/view
122-
{:style {:position :absolute
123-
:bottom 0
124-
:top 0
125-
:left 0
126-
:width (+ line-number-width 8 8)
127-
:background-color background-color-left
128-
:border-right-color border-color
129-
:border-right-width 1}}]
130-
(conj maybe-mask-wrapper
131-
[rn/view {:max-height max-text-height}
132-
[rn/view
133-
{:on-layout (fn [evt]
134-
(let [height (oops/oget evt "nativeEvent.layout.height")]
135-
(reset! text-height height)))}
136-
[code-block
137-
{:rows (take max-rows rows)
138-
:line-number-width line-number-width}]]])
49+
(defn- mask-view
50+
[{:keys [apply-mask?]} child]
51+
(if apply-mask?
52+
[:<>
53+
[rn/view {:style style/gradient-container}
54+
[linear-gradient/linear-gradient
55+
{:style style/gradient
56+
:colors [:transparent (style/gradient-color)]}
57+
[rn/view {:style style/gradient}]]]
58+
child]
59+
child))
13960

140-
;; Copy button
141-
[rn/view
142-
{:style {:position :absolute
143-
:bottom 8
144-
:right 8}}
145-
[button/button
146-
{:icon true
147-
:type :grey
148-
:size 24
149-
:on-press on-copy-press}
150-
:main-icons/copy]]]))))
61+
(defn- calc-line-number-width
62+
[font-scale rows-to-show]
63+
(let [max-line-digits (-> rows-to-show str count)]
64+
(if (= 1 max-line-digits)
65+
18 ;; ~ 9 is char width, 18 is width used in Figma.
66+
(* 9 max-line-digits font-scale))))
15167

152-
(defn- wrap-renderer-fn
153-
[f {:keys [max-lines on-copy-press]}]
154-
(fn [^js props]
155-
(reagent/as-element [:f> f
156-
{:rows (.-rows props)
157-
:max-lines max-lines
158-
:on-copy-press on-copy-press}])))
68+
(defn- native-renderer
69+
[{:keys [rows max-lines on-copy-press]
70+
:or {max-lines ##Inf}}]
71+
(let [font-scale (:font-scale (rn/use-window-dimensions))
72+
total-rows (count rows)
73+
number-rows-to-show (min (count rows) max-lines)
74+
line-number-width (calc-line-number-width font-scale number-rows-to-show)
75+
truncated? (< number-rows-to-show total-rows)
76+
rows-to-show-coll (if truncated?
77+
(as-> rows $
78+
(update $ number-rows-to-show assoc :last-line? true)
79+
(take (inc number-rows-to-show) $))
80+
rows)]
81+
[rn/view {:style (style/container)}
82+
[rn/view {:style (style/line-number-container line-number-width)}]
83+
[rn/view {:style (style/divider line-number-width)}]
84+
[mask-view {:apply-mask? truncated?}
85+
[code-block
86+
{:rows rows-to-show-coll
87+
:line-number-width line-number-width}]]
88+
[rn/view {:style style/copy-button}
89+
[button/button
90+
{:icon true
91+
:type :grey
92+
:size 24
93+
:on-press on-copy-press
94+
:override-background-color (style/button-background-color)}
95+
:main-icons/copy]]]))
15996

16097
(defn snippet
16198
[{:keys [language max-lines on-copy-press]} children]
16299
[highlighter/highlighter
163100
{:language language
164-
:renderer (wrap-renderer-fn
165-
native-renderer
166-
{:max-lines max-lines
167-
:on-copy-press #(when on-copy-press
168-
(on-copy-press children))})
169-
;; Default props to adapt Highlighter for react-native.
170-
;;:CodeTag react-native/View
171-
;;:PreTag react-native/View
101+
:renderer (fn [^js/Object props]
102+
(reagent/as-element
103+
[:f> native-renderer
104+
{:rows (-> props .-rows bean/->clj)
105+
:on-copy-press #(when on-copy-press (on-copy-press children))
106+
:max-lines max-lines}]))
172107
:show-line-numbers false
173-
:style #js {}
174-
:custom-style #js {:backgroundColor nil}}
108+
:style {}
109+
:custom-style {:background-color nil}}
175110
children])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
(ns quo2.components.links.url-preview.component-spec
2+
(:require
3+
[quo2.components.links.url-preview.view :as view]
4+
[test-helpers.component :as h]))
5+
6+
(h/describe "Links - URL Preview"
7+
(h/test "default render"
8+
(h/render [view/view])
9+
(h/is-truthy (h/query-by-label-text :title))
10+
(h/is-truthy (h/query-by-label-text :logo))
11+
(h/is-truthy (h/query-by-label-text :button-clear-preview))
12+
(h/is-null (h/query-by-label-text :url-preview-loading)))
13+
14+
(h/test "on-clear event"
15+
(let [on-clear (h/mock-fn)]
16+
(h/render [view/view {:on-clear on-clear}])
17+
(h/fire-event :press (h/get-by-label-text :button-clear-preview))
18+
(h/was-called on-clear)))
19+
20+
(h/describe "loading state"
21+
(h/test "shows a loading container"
22+
(h/render [view/view {:loading? true :loading-message "Hello"}])
23+
(h/is-null (h/query-by-label-text :title))
24+
(h/is-truthy (h/query-by-label-text :url-preview-loading)))
25+
26+
(h/test "renders if `loading-message` is not passed"
27+
(h/render [view/view {:loading? true}])
28+
(h/is-null (h/query-by-label-text :title))
29+
(h/is-truthy (h/query-by-label-text :url-preview-loading)))))

0 commit comments

Comments
 (0)