Lint & fix some shadowed core Clojure(Script) vars (#16500)

It's well known that shadowing core Clojure vars can lead to unexpected bugs. In
fact, it's a common source of bugs in other languages too. In the status-mobile
repository there are, in total, 562 shadowed vars, ~500 are core vars. Excluding
the "old code" we still have 285 offenders.

In status-mobile I've already seen two bugs caused by shadowed vars, both with
the shadowed var "name". But probably other problems happened in the past, and
others will happen in the future if we don't do something about this. This PR is
also my response to my frustration trying to review PRs and checking for
shadowed vars, humans were not meant for that!

In this commit we are enabling ":shadowed-var" to lint certain (not all) core
vars as errors (not warnings). In future PRs we can gradually unshadow more
vars. For the record, name is shadowed 40 times in the new code and 130 in
total, and type is shadowed 93 times in the new code and 124 in total!

What about non-core vars, should we allow shadowing? There are ~70 non-core
shadowed vars. In my opinion, we should also lint and disallow shadowing
non-core vars, since it may cause the same kind of bugs of shadowing core vars.
But this decision can be left for another moment/issue, after we have fixed the
most prominent problem of shadowing core vars.

Which vars are unshadowed in this PR? I fixed 62 errors and unshadowed
cljs.core/iter, cljs.core/time, cljs.core/count, cljs.core/key,
clojure.core/key.

Resources:

- [clj-kondo linter: shadowed-var](https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#shadowed-var)
This commit is contained in:
Icaro Motta 2023-07-06 10:28:07 +00:00 committed by GitHub
parent 4d7cf3e94e
commit 9ed68ee7d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 173 additions and 202 deletions

View File

@ -14,6 +14,13 @@
clojure.set set clojure.set set
clojure.walk walk clojure.walk walk
taoensso.timbre log}} taoensso.timbre log}}
:shadowed-var {:level :error
;; We temporarily use :include to define an
;; allowlist of core Clojure vars. In the
;; future, as we progressively fix shadowed
;; vars, we should be able to delete this
;; option and lint all vars.
:include [count iter key time]}
:invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]} :invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
;; TODO remove number when this is fixed ;; TODO remove number when this is fixed
;; https://github.com/borkdude/clj-kondo/issues/867 ;; https://github.com/borkdude/clj-kondo/issues/867

View File

@ -287,11 +287,11 @@
and then compressed. Example input/output : and then compressed. Example input/output :
input key = zQ3shTAten2v9CwyQD1Kc7VXAqNPDcHZAMsfbLHCZEx6nFqk9 and input key = zQ3shTAten2v9CwyQD1Kc7VXAqNPDcHZAMsfbLHCZEx6nFqk9 and
output key = 0x025596a7ff87da36860a84b0908191ce60a504afc94aac93c1abd774f182967ce6" output key = 0x025596a7ff87da36860a84b0908191ce60a504afc94aac93c1abd774f182967ce6"
[key callback] [input-key callback]
(log/info "[native-module] Deserializing and then compressing public key" (log/info "[native-module] Deserializing and then compressing public key"
{:fn :deserialize-and-compress-key {:fn :deserialize-and-compress-key
:key key}) :key input-key})
(.deserializeAndCompressKey ^js (status) key callback)) (.deserializeAndCompressKey ^js (status) input-key callback))
(defn compressed-key->public-key (defn compressed-key->public-key
"Provides compressed key to status-go and gets back the uncompressed public key via deserialization" "Provides compressed key to status-go and gets back the uncompressed public key via deserialization"

View File

@ -235,31 +235,6 @@
[value velocity snap-points] [value velocity snap-points]
(.snapPoint ^js redash value velocity (to-array snap-points))) (.snapPoint ^js redash value velocity (to-array snap-points)))
(defn cancelable-loop
[{:keys [clock duration finished on-reach]}]
(let [time (value 0)
frame-time (value 0)
position (value 0)
to-value (value 1)
state {:time time
:frameTime frame-time
:finished finished
:position position}
config {:toValue to-value
:duration duration
:easing (:linear easings)}]
(block
[(timing clock state config)
(cond* (and* finished
(eq position to-value))
(call* [] on-reach))
(cond* finished
[(set finished 0)
(set time 0)
(set frame-time 0)
(set position 0)])
position])))
(defn with-easing (defn with-easing
[{val :value [{val :value
:keys [snap-points velocity offset state easing duration :keys [snap-points velocity offset state easing duration

View File

@ -1,12 +1,5 @@
(ns quo.previews.preview) (ns quo.previews.preview)
(defn descriptor->values
[{:keys [key options type]}]
{key (case type
:boolean [false true]
:text [nil "Just simple text"] ; NOTE(Ferossgp): add example with long text?
:select (mapv :key options))})
(defmacro list-comp (defmacro list-comp
[[binding seq-expr & bindings] body-expr] [[binding seq-expr & bindings] body-expr]
(cond (not binding) (cond (not binding)

View File

@ -68,8 +68,8 @@
:background-color (:ui-background @colors/theme)}) :background-color (:ui-background @colors/theme)})
(defn customizer-boolean (defn customizer-boolean
[{:keys [label key state]}] [{:keys [label state] :as args}]
(let [state* (reagent/cursor state [key])] (let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container} [rn/view {:style container}
[label-view state label] [label-view state label]
[rn/view [rn/view
@ -95,8 +95,8 @@
"False"]]]])) "False"]]]]))
(defn customizer-text (defn customizer-text
[{:keys [label key state]}] [{:keys [label state] :as args}]
(let [state* (reagent/cursor state [key])] (let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container} [rn/view {:style container}
[label-view state label] [label-view state label]
[rn/view {:style {:flex 0.6}} [rn/view {:style {:flex 0.6}}
@ -117,8 +117,8 @@
(defn customizer-select (defn customizer-select
[] []
(let [open (reagent/atom nil)] (let [open (reagent/atom nil)]
(fn [{:keys [label key state options]}] (fn [{:keys [label state options] :as args}]
(let [state* (reagent/cursor state [key]) (let [state* (reagent/cursor state [(:key args)])
selected (value-for-key @state* options)] selected (value-for-key @state* options)]
[rn/view {:style container} [rn/view {:style container}
[label-view state label] [label-view state label]
@ -133,15 +133,15 @@
[rn/view {:style (modal-view)} [rn/view {:style (modal-view)}
[rn/scroll-view [rn/scroll-view
(doall (doall
(for [{:keys [key value]} options] (for [{k :key v :value} options]
^{:key key} ^{:key k}
[rn/touchable-opacity [rn/touchable-opacity
{:style (select-option-style (= @state* key)) {:style (select-option-style (= @state* k))
:on-press #(do :on-press #(do
(reset! open false) (reset! open false)
(reset! state* key))} (reset! state* k))}
[quo/text {:color (if (= @state* key) :link :secondary)} [quo/text {:color (if (= @state* k) :link :secondary)}
value]])) v]]))
[rn/view {:flex-direction :row} [rn/view {:flex-direction :row}
[rn/touchable-opacity [rn/touchable-opacity
{:style (select-option-style false) {:style (select-option-style false)
@ -175,17 +175,15 @@
{:style {:flex 1} {:style {:flex 1}
:padding-horizontal 16} :padding-horizontal 16}
(doall (doall
(for [{:keys [key type] (for [desc descriptors
:as desc} :let [descriptor (merge desc {:state state})]]
descriptors ^{:key (:key desc)}
:let [descriptor (merge desc
{:state state})]]
^{:key key}
[:<> [:<>
(case type (case (:type desc)
:boolean [customizer-boolean descriptor] :boolean [customizer-boolean descriptor]
:text [customizer-text descriptor] :text [customizer-text descriptor]
:select [customizer-select descriptor])]))]) :select [customizer-select descriptor]
nil)]))])
(comment (comment
[{:label "Show error:" [{:label "Show error:"

View File

@ -62,7 +62,7 @@
:customization-color customize jump-to and mention button color}" :customization-color customize jump-to and mention button color}"
[_] [_]
(let [pressed? (reagent/atom false)] (let [pressed? (reagent/atom false)]
(fn [{:keys [type label on-press count customization-color style]}] (fn [{:keys [type label on-press customization-color style] :as args}]
[rn/touchable-opacity [rn/touchable-opacity
{:on-press-in #(reset! pressed? true) {:on-press-in #(reset! pressed? true)
:on-press-out #(reset! pressed? false) :on-press-out #(reset! pressed? false)
@ -102,6 +102,6 @@
(case type (case type
:jump-to label :jump-to label
:search-with-label label :search-with-label label
(:mention :notification-down :notification-up) (str count))]) (:mention :notification-down :notification-up) (str (:count args)))])
(when (#{:jump-to :notification-down :notification-up} type) (when (#{:jump-to :notification-down :notification-up} type)
[icon-view type])]]))) [icon-view type])]])))

View File

@ -17,8 +17,8 @@
:outline colors/neutral-70}}) :outline colors/neutral-70}})
(defn get-color (defn get-color
[key] [k]
(get-in themes [(theme/get-theme) key])) (get-in themes [(theme/get-theme) k]))
(defn counter (defn counter
[{:keys [type override-text-color override-bg-color style accessibility-label max-value] [{:keys [type override-text-color override-bg-color style accessibility-label max-value]

View File

@ -14,8 +14,8 @@
:error colors/danger-60}}) :error colors/danger-60}})
(defn get-color (defn get-color
[key] [k]
(get-in themes [(theme/get-theme) key])) (get-in themes [(theme/get-theme) k]))
(defn info-message (defn info-message
"[info-message opts \"message\"] "[info-message opts \"message\"]

View File

@ -30,12 +30,12 @@
:close-button colors/white}}) :close-button colors/white}})
(defn get-color (defn get-color
[theme key] [theme k]
(get-in themes [theme key])) (get-in themes [theme k]))
(defn get-color-by-type (defn get-color-by-type
[theme type key] [theme type k]
(get-in themes [theme type key])) (get-in themes [theme type k]))
(defn container (defn container
[{:keys [theme type include-button?]}] [{:keys [theme type include-button?]}]

View File

@ -17,8 +17,8 @@
:background colors/neutral-95}}) :background colors/neutral-95}})
(defn get-color (defn get-color
[key] [k]
(get-in themes [(theme/get-theme) key])) (get-in themes [(theme/get-theme) k]))
(def ui-images (def ui-images
{:light {:horizontal (js/require "../resources/images/ui/message-gap-hborder-light.png") {:light {:horizontal (js/require "../resources/images/ui/message-gap-hborder-light.png")
@ -28,8 +28,8 @@
:circles (js/require "../resources/images/ui/message-gap-circle-bg-dark.png")}}) :circles (js/require "../resources/images/ui/message-gap-circle-bg-dark.png")}})
(defn get-image (defn get-image
[key] [k]
(get-in ui-images [(theme/get-theme) key])) (get-in ui-images [(theme/get-theme) k]))
;;; components ;;; components
;;;; borders ;;;; borders

View File

@ -5,12 +5,12 @@
(defn dynamic-button-view (defn dynamic-button-view
[type dynamic-buttons style] [type dynamic-buttons style]
(when-let [{:keys [count on-press customization-color label]} (get dynamic-buttons type)] (when-let [{:keys [on-press customization-color label] :as props} (get dynamic-buttons type)]
[dynamic-button/dynamic-button [dynamic-button/dynamic-button
{:type type {:type type
:label label :label label
:on-press on-press :on-press on-press
:count count :count (:count props)
:style style :style style
:customization-color customization-color}])) :customization-color customization-color}]))

View File

@ -150,8 +150,8 @@
[activity-reply-text-input props reply-input]) [activity-reply-text-input props reply-input])
(when items (when items
[rn/view style/footer-container [rn/view style/footer-container
(for [{:keys [key] :as item} items] (for [item items]
^{:key key} ^{:key (:key item)}
[footer-item-view item replying? reply-input])])]))) [footer-item-view item replying? reply-input])])])))
(defn view (defn view

View File

@ -30,10 +30,10 @@
:path-length path-length})) :path-length path-length}))
(defn- linear-ease (defn- linear-ease
[time start goal duration] [input-time start goal duration]
(if (zero? duration) (if (zero? duration)
start start
(-> time (-> input-time
(/ duration) (/ duration)
(* goal) (* goal)
(+ start)))) (+ start))))

View File

@ -4,10 +4,10 @@
[react-native.core :as rn])) [react-native.core :as rn]))
(defn info-count (defn info-count
([count] ([amount]
(info-count {} count)) (info-count {} amount))
([props count] ([props amount]
(when (> count 0) (when (> amount 0)
[rn/view [rn/view
(merge props (merge props
{:style (merge {:width 16 {:style (merge {:width 16
@ -23,4 +23,4 @@
{:style (merge typography/font-medium {:style (merge typography/font-medium
typography/label typography/label
{:color colors/white :text-align :center})} {:color colors/white :text-align :center})}
count]]))) amount]])))

View File

@ -41,8 +41,8 @@
:margin-right 8}) :margin-right 8})
(defn get-color-by-type (defn get-color-by-type
[type key] [type k]
(get-in themes [(theme/get-theme) type key])) (get-in themes [(theme/get-theme) type k]))
(defn account-selector (defn account-selector
"[account-selector opts] "[account-selector opts]
@ -73,4 +73,3 @@
:size :paragraph-1 :size :paragraph-1
:style {:color account-text-color}} :style {:color account-text-color}}
account-text]]])) account-text]]]))

View File

@ -33,7 +33,7 @@
(defn on-finalize [gesture handler] (.onFinalize ^js gesture handler)) (defn on-finalize [gesture handler] (.onFinalize ^js gesture handler))
(defn max-pointers [gesture count] (.maxPointers ^js gesture count)) (defn max-pointers [gesture amount] (.maxPointers ^js gesture amount))
(defn min-distance [gesture dist] (.minDistance ^js gesture dist)) (defn min-distance [gesture dist] (.minDistance ^js gesture dist))
@ -41,7 +41,7 @@
(defn hit-slop [gesture settings] (.hitSlop ^js gesture settings)) (defn hit-slop [gesture settings] (.hitSlop ^js gesture settings))
(defn number-of-taps [gesture count] (.numberOfTaps ^js gesture count)) (defn number-of-taps [gesture amount] (.numberOfTaps ^js gesture amount))
(defn enabled [gesture enabled?] (.enabled ^js gesture enabled?)) (defn enabled [gesture enabled?] (.enabled ^js gesture enabled?))

View File

@ -10,9 +10,9 @@
(def key->string str) (def key->string str)
(defn set-item! (defn set-item!
[key value] [k value]
(-> ^js async-storage (-> ^js async-storage
(.setItem (key->string key) (.setItem (key->string k)
(clj->transit value)) (clj->transit value))
(.catch (fn [error] (.catch (fn [error]
(log/error "[async-storage]" error))))) (log/error "[async-storage]" error)))))

View File

@ -53,19 +53,19 @@
"Takes the previous edit, either :gas or :gas-price and a value as string. "Takes the previous edit, either :gas or :gas-price and a value as string.
Wei for gas, and gwei for gas price. Wei for gas, and gwei for gas price.
Validates them and sets max fee" Validates them and sets max fee"
[edit-value key value] [edit-value k value]
(let [^js bn-value (money/bignumber value) (let [^js bn-value (money/bignumber value)
error-label-key (get-error-label-key key bn-value) error-label-key (get-error-label-key k bn-value)
data (if error-label-key data (if error-label-key
{:value value {:value value
:max-fee 0 :max-fee 0
:error (i18n/label error-label-key)} :error (i18n/label error-label-key)}
{:value value {:value value
:value-number (if (= :gasPrice key) :value-number (if (= :gasPrice k)
(money/->wei :gwei bn-value) (money/->wei :gwei bn-value)
bn-value)})] bn-value)})]
(-> edit-value (-> edit-value
(assoc key data) (assoc k data)
edit-max-fee))) edit-max-fee)))
;; TODO(rasom): this number is almost arbitrary, I was able to sent txs with ;; TODO(rasom): this number is almost arbitrary, I was able to sent txs with

View File

@ -186,8 +186,8 @@
text))}))))) text))})))))
(defn i18n-text (defn i18n-text
[{:keys [style key]}] [{style :style k :key}]
[text {:style style} (i18n/label key)]) [text {:style style} (i18n/label k)])
(defn touchable-opacity (defn touchable-opacity
[props content] [props content]

View File

@ -3,10 +3,10 @@
[status-im.ui.components.react :as react])) [status-im.ui.components.react :as react]))
(defn tab-title (defn tab-title
[state key label active?] [state k label active?]
[react/view {:align-items :center} [react/view {:align-items :center}
[react/touchable-highlight [react/touchable-highlight
{:on-press #(swap! state assoc :tab key) {:on-press #(swap! state assoc :tab k)
:underlay-color colors/gray-lighter :underlay-color colors/gray-lighter
:accessibility-label (str label "-item-button") :accessibility-label (str label "-item-button")
:style {:border-radius 8}} :style {:border-radius 8}}
@ -18,14 +18,14 @@
[react/view {:width 24 :height 3 :border-radius 4 :background-color colors/blue}])]) [react/view {:width 24 :height 3 :border-radius 4 :background-color colors/blue}])])
(defn tab-button (defn tab-button
[state key label active?] [state k label active?]
[react/view [react/view
{:flex 1 {:flex 1
:align-items :center :align-items :center
:border-radius 8 :border-radius 8
:background-color (if active? colors/blue colors/blue-light)} :background-color (if active? colors/blue colors/blue-light)}
[react/touchable-highlight [react/touchable-highlight
{:on-press #(swap! state assoc :tab key) {:on-press #(swap! state assoc :tab k)
:accessibility-label (str label "-item-button") :accessibility-label (str label "-item-button")
:style {:border-radius 8} :style {:border-radius 8}
:flex 1} :flex 1}

View File

@ -191,9 +191,9 @@
(icons/icon icon {:color :dark})]}]]) (icons/icon icon {:color :dark})]}]])
(defn card-body-row (defn card-body-row
[key value primary?] [k value primary?]
[react/view {:flex-direction :row} [react/view {:flex-direction :row}
[quo/text {:color (when-not primary? :secondary)} key] [quo/text {:color (when-not primary? :secondary)} k]
[quo/text [quo/text
{:style {:margin-right 4} {:style {:margin-right 4}
:color (when-not primary? :secondary)} ":"] :color (when-not primary? :secondary)} ":"]
@ -268,13 +268,13 @@
:on-change-text on-change}]]) :on-change-text on-change}]])
(defn help-label-kv (defn help-label-kv
[{:keys [key value]}] [{k :key v :value}]
[react/view {:style {:flex-direction :row}} [react/view {:style {:flex-direction :row}}
[quo/text {:color :secondary} key] [quo/text {:color :secondary} k]
[quo/text [quo/text
{:color :secondary {:color :secondary
:style {:margin-right 4}} ":"] :style {:margin-right 4}} ":"]
[quo/text {:color :secondary} value]]) [quo/text {:color :secondary} v]])
(defn nonce-modal (defn nonce-modal
[] []

View File

@ -31,5 +31,5 @@
(defn index-by (defn index-by
"Given a collection and a unique key function, returns a map that indexes the collection. "Given a collection and a unique key function, returns a map that indexes the collection.
Similar to group-by except that the map values are single objects (depends on key uniqueness)." Similar to group-by except that the map values are single objects (depends on key uniqueness)."
[key coll] [k coll]
(into {} (map #(vector (key %) %) coll))) (into {} (map #(vector (k %) %) coll)))

View File

@ -224,9 +224,9 @@
(.round (.dividedBy ^js bn1 bn2) 0)) (.round (.dividedBy ^js bn1 bn2) 0))
(defn format-members (defn format-members
[count] [amount]
(if (> count 1000000) (if (> amount 1000000)
(str (with-precision (/ count 1000000) 1) (i18n/label :t/M)) (str (with-precision (/ amount 1000000) 1) (i18n/label :t/M))
(if (and (> count 999) (< count 1000000)) (if (and (> amount 999) (< amount 1000000))
(str (with-precision (/ count 1000) 1) (i18n/label :t/K)) (str (with-precision (/ amount 1000) 1) (i18n/label :t/K))
count))) amount)))

View File

@ -44,14 +44,15 @@
[back-button] [options-button]]) [back-button] [options-button]])
(defn count-container (defn count-container
[count accessibility-label] [amount accessibility-label]
[rn/view [rn/view
{:style (style/count-container) {:style (style/count-container)
:accessibility-label accessibility-label} :accessibility-label accessibility-label}
[quo/text [quo/text
{:size :label {:size :label
:weight :medium :weight :medium
:style {:text-align :center}} count]]) :style {:text-align :center}}
amount]])
(defn contacts-section-header (defn contacts-section-header
[{:keys [title]}] [{:keys [title]}]

View File

@ -25,9 +25,9 @@
(defn filter-and-sort-items-by-tab (defn filter-and-sort-items-by-tab
[tab items] [tab items]
(let [key (if (= tab :tab/groups) :group-chat :chat-id)] (let [k (if (= tab :tab/groups) :group-chat :chat-id)]
(->> items (->> items
(filter key) (filter k)
(sort-by :timestamp >)))) (sort-by :timestamp >))))
(defn empty-state-content (defn empty-state-content

View File

@ -128,11 +128,11 @@
(defn update-message (defn update-message
"Update the message and siblings with positional info" "Update the message and siblings with positional info"
[tree message] [tree message]
(let [iter (red-black-tree/find tree message) (let [iterator (red-black-tree/find tree message)
previous-message (red-black-tree/get-prev iter) previous-message (red-black-tree/get-prev iterator)
next-message (red-black-tree/get-next iter) next-message (red-black-tree/get-next iterator)
message-with-pos-data (add-group-info message previous-message next-message)] message-with-pos-data (add-group-info message previous-message next-message)]
(cond-> (red-black-tree/update iter message-with-pos-data) (cond-> (red-black-tree/update iterator message-with-pos-data)
next-message next-message
(-> (red-black-tree/find next-message) (-> (red-black-tree/find next-message)
(red-black-tree/update (update-next-message message-with-pos-data next-message))) (red-black-tree/update (update-next-message message-with-pos-data next-message)))
@ -145,11 +145,11 @@
(defn remove-message (defn remove-message
"Remove a message in the list" "Remove a message in the list"
[tree prepared-message] [tree prepared-message]
(let [iter (red-black-tree/find tree prepared-message)] (let [iterator (red-black-tree/find tree prepared-message)]
(if (not iter) (if (not iterator)
tree tree
(let [new-tree (red-black-tree/remove iter) (let [new-tree (red-black-tree/remove iterator)
next-message (red-black-tree/get-next iter)] next-message (red-black-tree/get-next iterator)]
(if (not next-message) (if (not next-message)
new-tree new-tree
(update-message new-tree next-message)))))) (update-message new-tree next-message))))))

View File

@ -9,7 +9,7 @@
[status-im2.contexts.chat.photo-selector.album-selector.style :as style])) [status-im2.contexts.chat.photo-selector.album-selector.style :as style]))
(defn render-album (defn render-album
[{:keys [title count uri]} index _ {:keys [album? selected-album]}] [{title :title size :count uri :uri} index _ {:keys [album? selected-album]}]
(let [selected? (= selected-album title)] (let [selected? (= selected-album title)]
[rn/touchable-opacity [rn/touchable-opacity
{:on-press (fn [] {:on-press (fn []
@ -31,7 +31,7 @@
[quo/text [quo/text
{:size :paragraph-2 {:size :paragraph-2
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
(when count (str count " " (i18n/label :t/images)))]] (when size (str size " " (i18n/label :t/images)))]]
(when selected? (when selected?
[rn/view [rn/view
{:style {:position :absolute {:style {:position :absolute

View File

@ -20,8 +20,8 @@
:key :color :key :color
:type :select :type :select
:options (map (fn [color] :options (map (fn [color]
(let [key (get color :name)] (let [k (get color :name)]
{:key key :value key})) {:key k :value k}))
(quo/picker-colors))}]) (quo/picker-colors))}])
(defn cool-preview (defn cool-preview

View File

@ -10,8 +10,11 @@
[{:label "Color:" [{:label "Color:"
:key :color :key :color
:type :select :type :select
:options (map (fn [color] (let [key (get color :name)] {:key key :value key})) (quo/picker-colors))} :options (map (fn [color]
{:label "Blur:" (let [k (get color :name)]
{:key k :value k}))
(quo/picker-colors))}
{:label "Blur?"
:key :blur :key :blur
:type :boolean}]) :type :boolean}])
@ -43,4 +46,3 @@
:keyboard-should-persist-taps :always :keyboard-should-persist-taps :always
:header [cool-preview] :header [cool-preview]
:key-fn str}]]) :key-fn str}]])

View File

@ -18,8 +18,8 @@
:key :color :key :color
:type :select :type :select
:options (map (fn [color] :options (map (fn [color]
(let [key (get color :name)] (let [k (get color :name)]
{:key key :value key})) {:key k :value k}))
(quo/picker-colors))}]) (quo/picker-colors))}])
(defn cool-preview (defn cool-preview

View File

@ -72,8 +72,8 @@
:background-color (colors/theme-colors colors/neutral-20 colors/white)}) :background-color (colors/theme-colors colors/neutral-20 colors/white)})
(defn customizer-boolean (defn customizer-boolean
[{:keys [label key state]}] [{:keys [label state] :as args}]
(let [state* (reagent/cursor state [key])] (let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container} [rn/view {:style container}
[label-view state label] [label-view state label]
[rn/view [rn/view
@ -100,8 +100,8 @@
"False"]]]])) "False"]]]]))
(defn customizer-text (defn customizer-text
[{:keys [label key state limit suffix]}] [{:keys [label state limit suffix] :as args}]
(let [state* (reagent/cursor state [key])] (let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container} [rn/view {:style container}
[label-view state label] [label-view state label]
[rn/view {:style {:flex 0.6}} [rn/view {:style {:flex 0.6}}
@ -129,8 +129,8 @@
(defn customizer-select (defn customizer-select
[] []
(let [open (reagent/atom nil)] (let [open (reagent/atom nil)]
(fn [{:keys [label key state options]}] (fn [{:keys [label state options] :as args}]
(let [state* (reagent/cursor state [key]) (let [state* (reagent/cursor state [(:key args)])
selected (value-for-key @state* options)] selected (value-for-key @state* options)]
[rn/view {:style container} [rn/view {:style container}
[label-view state label] [label-view state label]
@ -145,15 +145,15 @@
[rn/view {:style (modal-view)} [rn/view {:style (modal-view)}
[rn/scroll-view [rn/scroll-view
(doall (doall
(for [{:keys [key value]} options] (for [{k :key v :value} options]
^{:key key} ^{:key k}
[rn/touchable-opacity [rn/touchable-opacity
{:style (select-option-style (= @state* key)) {:style (select-option-style (= @state* k))
:on-press #(do :on-press #(do
(reset! open false) (reset! open false)
(reset! state* key))} (reset! state* k))}
[rn/text {:color (if (= @state* key) :link :secondary)} [rn/text {:color (if (= @state* k) :link :secondary)}
value]]))] v]]))]
[rn/view [rn/view
{:flex-direction :row {:flex-direction :row
:padding-top 20 :padding-top 20
@ -192,17 +192,15 @@
{:style {:flex 1} {:style {:flex 1}
:padding-horizontal 16} :padding-horizontal 16}
(doall (doall
(for [{:keys [key type] (for [desc descriptors
:as desc} :let [descriptor (merge desc {:state state})]]
descriptors ^{:key (:key desc)}
:let [descriptor (merge desc
{:state state})]]
^{:key key}
[:<> [:<>
(case type (case (:type desc)
:boolean [customizer-boolean descriptor] :boolean [customizer-boolean descriptor]
:text [customizer-text descriptor] :text [customizer-text descriptor]
:select [customizer-select descriptor])]))]) :select [customizer-select descriptor]
nil)]))])
(comment (comment
[{:label "Show error:" [{:label "Show error:"

View File

@ -12,9 +12,9 @@
[status-im2.navigation.options :as options])) [status-im2.navigation.options :as options]))
(navigation/set-lazy-component-registrator (navigation/set-lazy-component-registrator
(fn [key] (fn [screen-key]
(let [screen (views/screen key)] (let [screen (views/screen screen-key)]
(navigation/register-component key (navigation/register-component screen-key
(fn [] (gesture/gesture-handler-root-hoc screen)) (fn [] (gesture/gesture-handler-root-hoc screen))
(fn [] screen))))) (fn [] screen)))))
@ -257,10 +257,9 @@
(re-frame/reg-fx (re-frame/reg-fx
:set-stack-root-fx :set-stack-root-fx
(fn [[stack comp]] (fn [[stack comp]]
;; We don't have bottom tabs as separate stacks anymore, ;; We don't have bottom tabs as separate stacks anymore,. So the old way of pushing screens in
;; So the old way of pushing screens in specific tabs will not work. ;; specific tabs will not work. Disabled set-stack-root for :shell-stack as it is not working
;; Disabled set-stack-root for :shell-stack as it is not working and ;; and currently only being used for browser and some rare keycard flows after login
;; currently only being used for browser and some rare keycard flows after login
(when-not (= @state/root-id :shell-stack) (when-not (= @state/root-id :shell-stack)
(log/debug :set-stack-root-fx stack comp) (log/debug :set-stack-root-fx stack comp)
(navigation/set-stack-root (navigation/set-stack-root

View File

@ -51,18 +51,18 @@
{:padding-top (safe-area/get-top)}))) {:padding-top (safe-area/get-top)})))
(defn screen (defn screen
[key] [screen-key]
(reagent.core/reactify-component (reagent.core/reactify-component
(fn [] (fn []
(let [{:keys [component options]} (get (if js/goog.DEBUG (let [{:keys [component options]} (get (if js/goog.DEBUG
(get-screens) (get-screens)
screens) screens)
(keyword key)) (keyword screen-key))
{:keys [insets sheet? theme]} options {:keys [insets sheet? theme]} options
user-theme (theme/get-theme) user-theme (theme/get-theme)
background-color (or (get-in options [:layout :backgroundColor]) background-color (or (get-in options [:layout :backgroundColor])
(when sheet? :transparent))] (when sheet? :transparent))]
^{:key (str "root" key @reloader/cnt)} ^{:key (str "root" screen-key @reloader/cnt)}
[theme/provider {:theme (or theme user-theme)} [theme/provider {:theme (or theme user-theme)}
[rn/view {:style (wrapped-screen-style insets background-color)} [rn/view {:style (wrapped-screen-style insets background-color)}
[inactive] [inactive]

View File

@ -12,14 +12,14 @@
(defn index-by (defn index-by
"Given a collection and a unique key function, returns a map that indexes the collection. "Given a collection and a unique key function, returns a map that indexes the collection.
Similar to group-by except that the map values are single objects (depends on key uniqueness)." Similar to group-by except that the map values are single objects (depends on key uniqueness)."
[key coll] [k coll]
(into {} (map #(vector (key %) %) coll))) (into {} (map #(vector (k %) %) coll)))
(defn distinct-by (defn distinct-by
"Given a key and a collection returns a unique collection by that key" "Given a key and a collection returns a unique collection by that key"
[key coll] [k coll]
(let [groups (group-by key coll)] (let [groups (group-by k coll)]
(map #(first (groups %)) (distinct (map key coll))))) (map #(first (groups %)) (distinct (map k coll)))))
(defn map-keys (defn map-keys
[f m] [f m]

View File

@ -148,9 +148,8 @@
(defn- to-str (defn- to-str
[ms old-fmt-fn yesterday-fmt-fn today-fmt-fn] [ms old-fmt-fn yesterday-fmt-fn today-fmt-fn]
(let [date (t.coerce/from-long ms) (let [date (t.coerce/from-long ms)
local (t/plus date time-zone-offset) ; NOTE(edge-case): this is wrong, it uses the current ;; NOTE(edge-case): this is wrong, it uses the current timezone offset, regardless of DST.
; timezone offset, local (t/plus date time-zone-offset)
; regardless of DST
today (t/minus (t/today-at-midnight) time-zone-offset) today (t/minus (t/today-at-midnight) time-zone-offset)
yesterday (t/plus today (t/days -1))] yesterday (t/plus today (t/days -1))]
(cond (cond
@ -235,15 +234,15 @@
:number diff :number diff
:time-intervals name})))) :time-intervals name}))))
(defn seconds-ago (defn seconds-ago
[time] [date-time]
(let [now (t/now)] (let [now (t/now)]
(if (<= (.getTime ^js time) (.getTime ^js now)) (if (<= (.getTime ^js date-time) (.getTime ^js now))
(t/in-seconds (t/interval time now)) (t/in-seconds (t/interval date-time now))
0))) 0)))
(defn time-ago (defn time-ago
[time] [date-time]
(let [diff (seconds-ago time) (let [diff (seconds-ago date-time)
unit (first (drop-while #(and (>= diff (:limit %)) unit (first (drop-while #(and (>= diff (:limit %))
(:limit %)) (:limit %))
units))] units))]
@ -253,8 +252,8 @@
(format-time-ago unit)))) (format-time-ago unit))))
(defn time-ago-long (defn time-ago-long
[time] [date-time]
(let [seconds-ago (seconds-ago time) (let [seconds-ago (seconds-ago date-time)
unit (first (drop-while #(and (>= seconds-ago (:limit %)) unit (first (drop-while #(and (>= seconds-ago (:limit %))
(:limit %)) (:limit %))
units)) units))

View File

@ -14,19 +14,19 @@
(js/clearTimeout v))) (js/clearTimeout v)))
(defn debounce-and-dispatch (defn debounce-and-dispatch
"Dispatches event only if there were no calls of this function in period of *time* ms" "Dispatches `event` iff it was not dispatched for the duration of `duration-ms`."
[event time] [event duration-ms]
(let [event-key (first event)] (let [event-key (first event)]
(clear event-key) (clear event-key)
(swap! timeout assoc event-key (js/setTimeout #(re-frame/dispatch event) time)))) (swap! timeout assoc event-key (js/setTimeout #(re-frame/dispatch event) duration-ms))))
(def chill (atom {})) (def chill (atom {}))
(defn dispatch-and-chill (defn dispatch-and-chill
"Dispateches event and ignores next calls in period of *time* ms" "Dispatches event and ignores subsequent calls for the duration of `duration-ms`."
[event time] [event duration-ms]
(let [event-key (first event)] (let [event-key (first event)]
(when-not (get @chill event-key) (when-not (get @chill event-key)
(swap! chill assoc event-key true) (swap! chill assoc event-key true)
(js/setTimeout #(swap! chill assoc event-key false) time) (js/setTimeout #(swap! chill assoc event-key false) duration-ms)
(re-frame/dispatch event)))) (re-frame/dispatch event))))

View File

@ -61,9 +61,9 @@
(def label (memoize label-fn)) (def label (memoize label-fn))
(defn label-pluralize (defn label-pluralize
[count path & options] [amount path & options]
(if (exists? (.t i18n)) (if (exists? (.t i18n))
(.p i18n count (name path) (clj->js options)) (.p i18n amount (name path) (clj->js options))
(name path))) (name path)))
(def locale (def locale

View File

@ -13,12 +13,12 @@
(.insert tree item)) (.insert tree item))
(defn update (defn update
[^js iter item] [^js iterator item]
(.update iter item)) (.update iterator item))
(defn remove (defn remove
[^js iter] [^js iterator]
(.remove iter)) (.remove iterator))
(defn get-values (defn get-values
[^js tree] [^js tree]
@ -26,26 +26,26 @@
(defn get-prev-element (defn get-prev-element
"Get previous item in the iterator, and wind it back to the initial state" "Get previous item in the iterator, and wind it back to the initial state"
[^js iter] [^js iterator]
(.prev iter) (.prev iterator)
(let [e (.-value iter)] (let [e (.-value iterator)]
(.next iter) (.next iterator)
e)) e))
(defn get-prev (defn get-prev
[^js iter] [^js iterator]
(when (.-hasPrev iter) (when (.-hasPrev iterator)
(get-prev-element iter))) (get-prev-element iterator)))
(defn get-next-element (defn get-next-element
"Get next item in the iterator, and wind it back to the initial state" "Get next item in the iterator, and wind it back to the initial state"
[^js iter] [^js iterator]
(.next iter) (.next iterator)
(let [e (.-value iter)] (let [e (.-value iterator)]
(.prev iter) (.prev iterator)
e)) e))
(defn get-next (defn get-next
[^js iter] [^js iterator]
(when (.-hasNext iter) (when (.-hasNext iterator)
(get-next-element iter))) (get-next-element iterator)))